﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;
using System.Net.Http.Headers;
using System.IO;
using System.Threading;
using System.Diagnostics;

namespace FutianCloudAPIService.Utils
{
    public class WebUtil
    {
        public static  Task<string> Get(string url, IEnumerable<KeyValuePair<string, string>> queryData = null, Action<HttpClient> buildHeaders = null)
        {
            var httpClient = new HttpClient();
            buildHeaders?.Invoke(httpClient);

            if (queryData != null)
                url = BuildUriQuery(url, queryData);

            return  httpClient.GetStringAsync(new Uri(url));
        }

        public static  async Task<string> Post(string url, IEnumerable<KeyValuePair<string, object>> data, IEnumerable<KeyValuePair<string, string>> queryData = null, Action<HttpClient> buildHeaders = null)
        {
            var httpClient = new HttpClient(new LoggingHandler(new HttpClientHandler()));
            buildHeaders?.Invoke(httpClient);
            if (queryData != null)
                url = BuildUriQuery(url, queryData);

            using (var formData = new MultipartFormDataContent())
            {
                foreach (var item in data)
                {
                    HttpContent content = null;
                    if (item.Value is string)
                    {
                        content = new StringContent(item.Value.ToString());
                        formData.Add(content, item.Key);
                    }
                    else if(item.Value is Stream)
                    {
                        content = new StreamContent(item.Value as Stream);
                        formData.Add(content, item.Key, item.Key);
                    }
                    else if (item.Value is byte[])
                    {
                        content = new ByteArrayContent(item.Value as byte[]);
                        formData.Add(content, item.Key);
                    }
                        
                }

              
                var responseMessage = await httpClient.PostAsync(new Uri(url), formData);
               
                return await responseMessage.Content.ReadAsStringAsync();
            }
        }
    

        private static string BuildUriQuery(string url, IEnumerable<KeyValuePair<string, string>> queryData)
        {
            var baseUri = new UriBuilder(url);

            string query;
            using (var content = new FormUrlEncodedContent(queryData))
            {
                query = content.ReadAsStringAsync().Result;
            }

            if (baseUri.Query != null && baseUri.Query.Length > 1)
                baseUri.Query = baseUri.Query.Substring(1) + "&" + query;
            else
                baseUri.Query = query;

            return baseUri.ToString();
        }
    }

    public class MyFormUrlEncodedContent : ByteArrayContent
    {
        public MyFormUrlEncodedContent(IEnumerable<KeyValuePair<string, string>> nameValueCollection)
            : base(MyFormUrlEncodedContent.GetContentByteArray(nameValueCollection))
        {
            base.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
        }
        private static byte[] GetContentByteArray(IEnumerable<KeyValuePair<string, string>> nameValueCollection)
        {
            if (nameValueCollection == null)
            {
                throw new ArgumentNullException("nameValueCollection");
            }
            StringBuilder stringBuilder = new StringBuilder();
            foreach (KeyValuePair<string, string> current in nameValueCollection)
            {
                if (stringBuilder.Length > 0)
                {
                    stringBuilder.Append('&');
                }

                stringBuilder.Append(MyFormUrlEncodedContent.Encode(current.Key));
                stringBuilder.Append('=');
                stringBuilder.Append(MyFormUrlEncodedContent.Encode(current.Value));
            }
            return Encoding.Default.GetBytes(stringBuilder.ToString());
        }
        private static string Encode(string data)
        {
            if (string.IsNullOrEmpty(data))
            {
                return string.Empty;
            }

            return WebUtility.HtmlEncode(data).Replace("%20", "+");
        }
    }

    public class LoggingHandler: DelegatingHandler
    {
        public LoggingHandler(HttpMessageHandler innerHandler)
        : base(innerHandler)
        {
        }

        protected override  Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            return base.SendAsync(request,cancellationToken);
        }
    }
}
